package com.yt.lxh.product.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.yt.lxh.common.exception.ServiceException;
import com.yt.lxh.common.exception.SqlHandlerException;
import com.yt.lxh.common.result.ResultCodeEnum;
import com.yt.lxh.common.service.CacheService;
import com.yt.lxh.common.service.CheckLogin;
import com.yt.lxh.constant.ProductConstant;
import com.yt.lxh.constant.SQLConstant;
import com.yt.lxh.model.acl.Admin;
import com.yt.lxh.vo.product.TasteAttrVO;
import com.yt.lxh.vo.product.TasteListVO;
import com.yt.lxh.model.product.Taste;
import com.yt.lxh.model.product.TasteAttr;
import com.yt.lxh.dto.product.SaveTasteDTO;
import com.yt.lxh.dto.product.UpdateTasteDTO;
import com.yt.lxh.product.mapper.TasteAttrMapper;
import com.yt.lxh.product.mapper.TasteMapper;
import com.yt.lxh.product.service.TasteService;
import com.yt.lxh.dto.common.BasePageDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author yzk789
 * @since 2023-10-18
 */
@Service
public class TasteServiceImpl extends ServiceImpl<TasteMapper, Taste> implements TasteService {
    @Autowired
    private TasteMapper tasteMapper;

    @Autowired
    private TasteAttrMapper tasteAttrMapper;

    @Autowired
    private CheckLogin checkLogin;

    @Autowired
    private CacheService cacheService;

    /**
     * 新增口味
     *
     * @param saveTasteDTO 新增口味数据对象
     * @param token       请求头Token
     */
    @Override
    public void saveTaste(SaveTasteDTO saveTasteDTO, String token) {
        // 获取用户信息
        Admin admin = checkLogin.checkAdminLogin();
        Taste taste = tasteMapper.selectOne(Wrappers.<Taste>lambdaQuery().eq(Taste::getTasteName, saveTasteDTO.getTasteName()));
        // 判断数据是否重复
        if (taste != null) {
            throw new ServiceException(ResultCodeEnum.DATA_EXIST, saveTasteDTO.getTasteName() + "已存在");
        }
        // 补全参数
        taste = new Taste();
        taste.setTasteName(saveTasteDTO.getTasteName());
        taste.setCreateUser(admin.getUsername());
        taste.setUpdateUser(admin.getUsername());
        int row = tasteMapper.insert(taste);
        // 新增失败，数据库异常
        if (row == 0) {
            throw new SqlHandlerException(SQLConstant.INSERT_FAIL + " ---> TasteServiceImpl.saveTaste");
        }
        // 判断口味属性列表是否传入，新增口味属性
        if (saveTasteDTO.getTasteAttrs() != null && saveTasteDTO.getTasteAttrs().size() > 0) {
            // 循环新增
            for (TasteAttr tasteAttr : saveTasteDTO.getTasteAttrs()) {
                // 如果当前口味属性已经存在，则直接进入下一次循环
                boolean isExist = tasteAttrMapper.selectOne(Wrappers.<TasteAttr>lambdaQuery()
                        .eq(TasteAttr::getAttrName, tasteAttr.getAttrName())
                        .eq(TasteAttr::getTasteId, taste.getId().toString())) != null;
                if (isExist) continue;
                // 校验金额是否合法
                validExtraPrice(tasteAttr.getExtraPrice());
                tasteAttr.setTasteId(taste.getId().toString());
                tasteAttr.setSort(tasteAttr.getSort());
                tasteAttr.setCreateUser(admin.getUsername());
                tasteAttr.setUpdateUser(admin.getUsername());
                tasteAttrMapper.insert(tasteAttr);
            }
        }
        // 将最新的数据存入缓存
        saveTasteToCache();
    }

    /**
     * 获取全部口味数据
     * @return
     */
    @Override
    public List<TasteListVO> getTasteAll() {
        List<TasteListVO> tasteListByCache = parseTasteListByCache();
        if (tasteListByCache == null || tasteListByCache.size() == 0) {
            // 缓存没有从数据库拿
            return saveTasteToCache();
        } else {
            // 返回缓存中的数据
            return tasteListByCache;
        }
    }

    /**
     * 分页查询
     *
     * @param basePageDTO 分页基本数据
     * @return
     */
    @Override
    public PageInfo<TasteListVO> getTastePage(BasePageDTO basePageDTO) {
        // 分页数据处理
        PageHelper.startPage(basePageDTO.getPageNum(), basePageDTO.getPageSize());
        List<TasteListVO> page = tasteMapper.page(basePageDTO.getQueryField());
        return new PageInfo<>(page);
    }

    /**
     * 更新口味及口味属性
     *
     * @param updateTasteDTO 更新口味数据对象
     * @param token         请求头Token
     */
    @Override
    public void updateTaste(UpdateTasteDTO updateTasteDTO, String token) {
        // 获取用户信息
        Admin admin = checkLogin.checkAdminLogin();
        int row = tasteMapper.update(null, Wrappers.<Taste>lambdaUpdate()
                .set(Taste::getTasteName, updateTasteDTO.getTasteName())
                .set(Taste::getUpdateUser, admin.getUsername())
                .eq(Taste::getId, updateTasteDTO.getTasteId()));
        // 更新行数为0，ID不存在
        if (row == 0) {
            throw new ServiceException(ResultCodeEnum.DATA_NOT_EXIST);
        }
        // 判断口味属性列表是否传入，新增或者更新口味属性
        if (updateTasteDTO.getTasteAttrs() != null && updateTasteDTO.getTasteAttrs().size() > 0) {
            List<Long> removeIds = new ArrayList<>(); // 排除删除的ID列表
            for (TasteAttr tasteAttr : updateTasteDTO.getTasteAttrs()) {
                // 如果当前口味属性已经存在，则直接进入下一次循环
                boolean isExist = tasteAttrMapper.selectOne(Wrappers.<TasteAttr>lambdaQuery()
                        .eq(TasteAttr::getAttrName, tasteAttr.getAttrName())
                        .eq(TasteAttr::getTasteId, updateTasteDTO.getTasteId())) != null;
                if (isExist) continue;
                // 校验金额是否合法
                validExtraPrice(tasteAttr.getExtraPrice());
                tasteAttr.setTasteId(updateTasteDTO.getTasteId());
                tasteAttr.setSort(tasteAttr.getSort());
                tasteAttr.setCreateUser(admin.getUsername());
                tasteAttr.setUpdateUser(admin.getUsername());
                // 存在则更新，不存在则插入
                tasteAttrMapper.insertOrUpdateByTasteAttr(tasteAttr);
                removeIds.add(tasteAttr.getId()); // 排除此次操作的ID
            }
            // 根据排除删除的ID列表，删除当前口味的其他属性
            if (removeIds.size() > 0) {
                tasteAttrMapper.update(null, Wrappers.<TasteAttr>lambdaUpdate()
                        .set(TasteAttr::getIsDeleted, SQLConstant.DELETED)
                        .set(TasteAttr::getUpdateUser, admin.getUsername())
                        .eq(TasteAttr::getTasteId, updateTasteDTO.getTasteId())
                        .notIn(TasteAttr::getId, removeIds));
            }
        } else {
            // 口味属性列表为空，则删除所有当前口味的属性
            tasteAttrMapper.update(null, Wrappers.<TasteAttr>lambdaUpdate()
                    .set(TasteAttr::getIsDeleted, SQLConstant.DELETED)
                    .set(TasteAttr::getUpdateUser, admin.getUsername())
                    .eq(TasteAttr::getTasteId, updateTasteDTO.getTasteId()));
        }
        // 将最新的数据存入缓存
        saveTasteToCache();
    }

    /**
     * 根据ID逻辑删除口味，对应的口味属性则永久删除
     *
     * @param id 要删除的口味ID
     */
    @Override
    public void delTasteById(String id, String token) {
        // 获取用户信息
        Admin admin = checkLogin.checkAdminLogin();
        int row = tasteMapper.update(null, Wrappers.<Taste>lambdaUpdate()
                .set(Taste::getIsDeleted, SQLConstant.DELETED)
                .set(Taste::getUpdateUser, admin.getUsername())
                .eq(Taste::getId, id));
        // 删除行数为0，ID不存在
        if (row == 0) {
            throw new ServiceException(ResultCodeEnum.DATA_NOT_EXIST);
        }
        // 删除对应的口味属性
        tasteAttrMapper.update(null, Wrappers.<TasteAttr>lambdaUpdate()
                .set(TasteAttr::getIsDeleted, SQLConstant.DELETED)
                .set(TasteAttr::getUpdateUser, admin.getUsername())
                .eq(TasteAttr::getTasteId, id));
        // 将最新的数据存入缓存
        saveTasteToCache();
    }

    /**
     * 根据ID列表逻辑删除口味，对应的口味属性则永久删除
     *
     * @param idList 口味ID列表
     */
    @Override
    public void delTasteByBatchIds(List<String> idList, String token) {
        // 获取用户信息
        Admin admin = checkLogin.checkAdminLogin();
        int row = tasteMapper.update(null, Wrappers.<Taste>lambdaUpdate()
                .set(Taste::getIsDeleted, SQLConstant.DELETED)
                .set(Taste::getUpdateUser, admin.getUsername())
                .in(Taste::getId, idList));
        // 删除行数为0，ID不存在
        if (row == 0) {
            throw new ServiceException(ResultCodeEnum.DATA_NOT_EXIST);
        }
        tasteAttrMapper.update(null, Wrappers.<TasteAttr>lambdaUpdate()
                .set(TasteAttr::getIsDeleted, SQLConstant.DELETED)
                .set(TasteAttr::getUpdateUser, admin.getUsername())
                .in(TasteAttr::getTasteId, idList));
        // 将最新的数据存入缓存
        saveTasteToCache();
    }

    // 校验口味属性额外金额是否合法
    private boolean validExtraPrice(BigDecimal price) {
        // 校验金额是否合法，进行比较不得小于 0
        if (price != null) {
            int validPrice = price.compareTo(new BigDecimal(0));
            if (validPrice == -1) {
                throw new ServiceException(ResultCodeEnum.PARAM_INVALID);
            }
        }
        return true;
    }

    /**
     * 将最新的口味数据存入缓存
     */
    private List<TasteListVO> saveTasteToCache() {
        // 类别数据在缓存中的标识  LuXueHe_TASTE
        String cacheKey = ProductConstant.TASTE_CACHE_KEY;
        // 删除缓存中的旧数据
        cacheService.delete(cacheKey);
        // 查询新数据，且类别已启用
        List<TasteListVO> tasteList = tasteMapper.getAll();
        // 没有记录，缓存 null
        if (!(tasteList != null && tasteList.size() > 0))
            cacheService.lLeftPush(cacheKey, null);
        // 将新数据存入缓存
        for (TasteListVO taste : tasteList) {
            cacheService.lLeftPush(cacheKey, JSON.toJSONString(taste));
        }
        return tasteList;
    }

    /**
     * 解析缓存里的数据
     */
    private List<TasteListVO> parseTasteListByCache() {
        // 类别数据在缓存中的标识  Luxuehe_TASTE
        String cacheKey = ProductConstant.TASTE_CACHE_KEY;
        List<String> JsonString = cacheService.lRange(cacheKey, 0, -1);
        if (JsonString.size() == 0) return null;
        // 解析JsonString 为 数组
        List<TasteListVO> tasteList = JsonString.stream()
                .map(item -> {
                    // 解析成 JSONObject 对象，方便后续
                    JSONObject jsonObject = JSON.parseObject(item);
                    // 字符串数据，通过 getString 拿取
                    String tasteId = jsonObject.getString("tasteId");
                    String tasteName = jsonObject.getString("tasteName");
                    // tasteAttrs 本身为数组，故而解析成 JSONArray
                    JSONArray tasteAttrs = jsonObject.getJSONArray("tasteAttrs");
                    // 转为 Java数组 List
                    List<TasteAttrVO> tasteAttrVOS = tasteAttrs.toJavaList(TasteAttrVO.class);
                    // 通过构造函数返回
                    return new TasteListVO(tasteId, tasteName, tasteAttrVOS);
                })
                .collect(Collectors.toList());
        return tasteList;
    }
}



